package com.yzh.pinboard.BoardView;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Rect;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
 * Created by Rex on 2017/3/1.
 */

public class ClipOperate {

    //<editor-fold desc="EraserOpe">
    public static void eraserByRect(Clip cleanClip, List<Stroke> newSendStroke, List<Stroke> deleteSendStroke, Rect cleanRect) {
        for (int i = cleanClip.strokes.size() - 1; i >= 0; i--) {
            if (isStrokeInRect(cleanClip.strokes.get(i), cleanRect)) {
                boolean isDeletePoint = false;
                for (int j = 0; j < cleanClip.strokes.get(i).points.size(); j++) {

                    if (isPointInXY(cleanClip.strokes.get(i).points.get(j), cleanRect)) {
                        isDeletePoint = true;
                        cleanClip.strokes.get(i).points.get(j).isDelete = true;
                    } else {
                        cleanClip.strokes.get(i).points.get(j).isDelete = false;
                    }
                }

                if (isDeletePoint) {

                    boolean isInNew = false;
                    for (int j = 0; j < newSendStroke.size(); j++) {
                        if (newSendStroke.get(j).id == cleanClip.strokes.get(i).id) {
                            newSendStroke.remove(j);
                            isInNew = true;
                            break;
                        }
                    }
                    if (!isInNew) {
                        deleteSendStroke.add(cleanClip.strokes.get(i));
                    }

                    List<Stroke> strokesNew = getStrokes(cleanClip.strokes.get(i), cleanRect);
                    cleanClip.strokes.remove(i);
                    for (int j = 0; j < strokesNew.size(); j++) {
                        cleanClip.strokes.add(strokesNew.get(j));
                        newSendStroke.add(strokesNew.get(j));
                    }
                }
            }
        }
        //return cleanClip;
    }

    private static boolean isStrokeInRect(Stroke mStroke, Rect mRect) {
        if (mStroke.GetMaxX() < mRect.left || mStroke.GetMinX() > mRect.right || mStroke.GetMaxY() < mRect.bottom || mStroke.GetMinY() > mRect.top) {
            return false;
        }
        return true;
    }

    private static boolean isPointInXY(Point mPoint, Rect mRect) {

        if (mPoint.X > mRect.left && mPoint.X < mRect.right && mPoint.Y > mRect.bottom && mPoint.Y < mRect.top) {
            return true;
        }
        return false;
    }

    private static List<Stroke> getStrokes(Stroke mStroke, Rect mRect) {

        List<Point> newPoints = new ArrayList<>();
        List<Stroke> newStrokes = new ArrayList<>();

        Point point1 = new Point();
        Point point2 = new Point();
        Point point3 = new Point();
        Point newPoint = new Point();

        for (int i = 0; i < mStroke.points.size(); i++) {
            if (mStroke.points.get(i).isDelete && newPoints.size() > 0) {
                if (i - 1 >= 0 && i + 1 < mStroke.points.size()) {
                    point1.X = (mStroke.points.get(i - 1).X + mStroke.points.get(i).X) / 2;
                    point1.Y = (mStroke.points.get(i - 1).Y + mStroke.points.get(i).Y) / 2;
                    point2.X = mStroke.points.get(i).X;
                    point2.Y = mStroke.points.get(i).Y;
                    point3.X = (mStroke.points.get(i + 1).X + mStroke.points.get(i).X) / 2;
                    point3.Y = (mStroke.points.get(i + 1).Y + mStroke.points.get(i).Y) / 2;

                    newPoint = caculateNewPoint(point1, point2, point3, mRect);
                    if (newPoint.X == point2.X && newPoint.Y == point2.Y) {
                        if (i < mStroke.points.size() - 2) {
                            point1.X = (mStroke.points.get(i + 1).X + mStroke.points.get(i).X) / 2;
                            point1.Y = (mStroke.points.get(i + 1).Y + mStroke.points.get(i).Y) / 2;
                            point2.X = mStroke.points.get(i + 1).X;
                            point2.Y = mStroke.points.get(i + 1).Y;
                            point3.X = (mStroke.points.get(i + 1).X + mStroke.points.get(i + 2).X) / 2;
                            point3.Y = (mStroke.points.get(i + 1).Y + mStroke.points.get(i + 2).Y) / 2;
                        } else {
                            point1.X = mStroke.points.get(i).X;
                            point1.Y = mStroke.points.get(i).Y;
                            point2.X = (mStroke.points.get(i + 1).X + mStroke.points.get(i).X) / 2;
                            point2.Y = (mStroke.points.get(i + 1).Y + mStroke.points.get(i).Y) / 2;
                            point3.X = mStroke.points.get(i + 1).X;
                            point3.Y = mStroke.points.get(i + 1).Y;
                        }

                        newPoint = caculateNewPoint(point1, point2, point3, mRect);

                    }
                    if (newPoint.X > 0) {
                        newPoints.add(newPoint);
                    }
                } else if (i - 1 > 0 && i == mStroke.points.size() - 1) {
                    point1.X = mStroke.points.get(i - 1).X;
                    point1.Y = mStroke.points.get(i - 1).Y;
                    point2.X = (mStroke.points.get(i - 1).X + mStroke.points.get(i).X) / 2;
                    point2.Y = (mStroke.points.get(i - 1).Y + mStroke.points.get(i).Y) / 2;
                    point3.X = mStroke.points.get(i).X;
                    point3.Y = mStroke.points.get(i).Y;
                    newPoint = caculateNewPoint(point1, point2, point3, mRect);
                    if (newPoint.X == point2.X && point2.Y == newPoint.Y) {
                        point1.Y = mStroke.points.get(i - 1).Y;
                        point1.X = mStroke.points.get(i - 1).X;
                        point2.X = (mStroke.points.get(i - 1).X + mStroke.points.get(i).X) / 2;
                        point2.Y = (mStroke.points.get(i - 1).Y + mStroke.points.get(i).Y) / 2;
                        point3.X = mStroke.points.get(i).X;
                        point3.Y = mStroke.points.get(i).Y;
                        newPoint = caculateNewPoint(point1, point2, point3, mRect);
                    }

                    if (newPoint.X > 0) {
                        newPoints.add(newPoint);
                    }
                }

                newStrokes.add(createStroke(mStroke, newPoints));
                newPoints.clear();
                continue;
            } else if (mStroke.points.get(i).isDelete) {
                continue;
            } else {
                if (newPoints.size() == 0 && i >= 1 && i < mStroke.points.size() - 1) {
                    point3.X = (mStroke.points.get(i + 1).X + mStroke.points.get(i).X) / 2;
                    point3.Y = (mStroke.points.get(i + 1).Y + mStroke.points.get(i).Y) / 2;
                    point1.X = (mStroke.points.get(i - 1).X + mStroke.points.get(i).X) / 2;
                    point1.Y = (mStroke.points.get(i - 1).Y + mStroke.points.get(i).Y) / 2;
                    point2.X = mStroke.points.get(i).X;
                    point2.Y = mStroke.points.get(i).Y;
                    newPoint = caculateNewPoint(point1, point2, point3, mRect);
                    if (newPoint.X == point2.X && newPoint.Y == point2.Y) {
                        if (i >= 2) {
                            point2.X = (mStroke.points.get(i - 1).X + mStroke.points.get(i).X) / 2;
                            point2.Y = (mStroke.points.get(i - 1).Y + mStroke.points.get(i).Y) / 2;
                            point1.X = (mStroke.points.get(i - 2).X + mStroke.points.get(i - 1).X) / 2;
                            point1.Y = (mStroke.points.get(i - 2).Y + mStroke.points.get(i - 1).Y) / 2;
                            point3.X = mStroke.points.get(i).X;
                            point3.Y = mStroke.points.get(i).Y;
                        } else {
                            point2.X = (mStroke.points.get(i - 1).X + mStroke.points.get(i).X) / 2;
                            point2.Y = (mStroke.points.get(i - 1).Y + mStroke.points.get(i).Y) / 2;
                            point3.X = mStroke.points.get(i).X;
                            point3.Y = mStroke.points.get(i).Y;
                            point1.X = mStroke.points.get(i - 1).X;
                            point1.Y = mStroke.points.get(i - 1).Y;
                        }
                        newPoint = caculateNewPoint(point1, point2, point3, mRect);
                    }
                    if (newPoint.X > 0) {
                        newPoints.add(newPoint);
                    }
                }
                if (newPoints.size() == 0 && i > 0 && i == mStroke.points.size() - 1) {
                    point2.X = mStroke.points.get(i - 1).X;
                    point2.Y = mStroke.points.get(i - 1).Y;
                    point3.X = mStroke.points.get(i).X;
                    point3.Y = mStroke.points.get(i).Y;
                    point1.X = mStroke.points.get(i - 1).X;
                    point1.Y = mStroke.points.get(i - 1).Y;

                    newPoint = caculateNewPoint(point1, point2, point3, mRect);

                    if (newPoint.X == 0) {

                        point2.X = (mStroke.points.get(i - 1).X + mStroke.points.get(i).X) / 2;
                        point2.Y = (mStroke.points.get(i - 1).Y + mStroke.points.get(i).Y) / 2;
                        point3.X = mStroke.points.get(i).X;
                        point3.Y = mStroke.points.get(i).Y;
                        point1.X = mStroke.points.get(i - 1).X;
                        point1.Y = mStroke.points.get(i - 1).Y;

                        newPoint = caculateNewPoint(point1, point2, point3, mRect);

                        if (newPoint.X == 0) {
                            newPoint = caculateNewPoint(point1, point3, point3, mRect);
                        }
                    }

                    if (newPoint.X > 0) {
                        newPoints.add(newPoint);
                    }
                }
                newPoints.add(mStroke.points.get(i));
            }
        }

        if (newPoints.size() > 0) {
            newStrokes.add(createStroke(mStroke, newPoints));
        }

        return newStrokes;
    }

    private static Point caculateNewPoint(Point point1, Point point2, Point point3, Rect mRect) {
        float t = 0;
        Point p1 = point1;
        Point cp = point2;
        Point p2 = point3;

        float c1x;
        float c1y;
        float c2x;
        float c2y;

        float px = 0f;
        float py = 0f;

        float distence = 2000;
        Point p = new Point();
        p.X = px;
        p.Y = py;

        while (t < 1) {

            c1x = p1.X + (cp.X - p1.X) * t;
            c1y = p1.Y + (cp.Y - p1.Y) * t;

            c2x = cp.X + (p2.X - cp.X) * t;
            c2y = cp.Y + (p2.Y - cp.Y) * t;

            px = c1x + (c2x - c1x) * t;
            py = c1y + (c2y - c1y) * t;

            Point pIn = new Point();
            pIn.Y = py;
            pIn.X = px;

            if (!isPointInXY(pIn, mRect)) {
                t = t + 0.01f;
                continue;
            }

            if (distence > Math.sqrt(Math.pow(px - mRect.left, 2))) {
                distence = (float) Math.sqrt(Math.pow(px - mRect.left, 2));
                p.X = px;
                p.Y = py;
            }

            if (distence > Math.sqrt(Math.pow(px - mRect.right, 2))) {
                distence = (float) Math.sqrt(Math.pow(px - mRect.right, 2));
                p.X = px;
                p.Y = py;
            }

            if (distence > Math.sqrt(Math.pow(py - mRect.bottom, 2))) {
                distence = (float) Math.sqrt(Math.pow(py - mRect.bottom, 2));
                p.X = px;
                p.Y = py;
            }

            if (distence > Math.sqrt(Math.pow(py - mRect.top, 2))) {
                distence = (float) Math.sqrt(Math.pow(py - mRect.top, 2));
                p.X = px;
                p.Y = py;
            }

            t = t + 0.01f;
        }

        if (p.X == 0f) {
            return cp;
        }
        return p;
    }

    private static Stroke createStroke(Stroke mStroke, List<Point> points) {
        Stroke reStroke = new Stroke();
        reStroke.id = UUID.randomUUID().toString();
        reStroke.points.addAll(points);
        reStroke.color = mStroke.color;
        reStroke.width = mStroke.width;
        return reStroke;
    }

    public static void calculateRect(Rect cleanRect, Clip cleanClip) {
        cleanRect.bottom = (int) ((cleanRect.bottom - cleanClip.matrix.offsetY) / cleanClip.matrix.m22);
        cleanRect.top = (int) ((cleanRect.top - cleanClip.matrix.offsetY) / cleanClip.matrix.m22);
        cleanRect.left = (int) ((cleanRect.left - cleanClip.matrix.offsetX) / cleanClip.matrix.m11);
        cleanRect.right = (int) ((cleanRect.right - cleanClip.matrix.offsetX) / cleanClip.matrix.m11);
    }


    //</editor-fold>

    //<editor-fold desc="ClipOpe">

    //画页面
    public static void drawClip(Clip mClip, Bitmap drawBitmap, Paint mPain) {
        //drawBitmap = Bitmap.createBitmap(mClip.clipWidth, mClip.clipHeight, Bitmap.Config.ARGB_8888);
        //drawElement(mClip,drawBitmap);
        Canvas drawCanvas = new Canvas(drawBitmap);
        drawCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        PaintFlagsDrawFilter pfd = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        drawCanvas.setDrawFilter(pfd);

        //drawElement(mClip,drawBitmap);

        drawCanvas.translate(mClip.matrix.offsetX, mClip.matrix.offsetY);
        drawCanvas.scale(mClip.matrix.m11, mClip.matrix.m22);
        //drawCanvas.drawColor(Color.BLACK);
        //drawElement(mClip,drawBitmap);
        if (mClip.strokes.size() > 0) {
            for (int i = 0; i < mClip.strokes.size(); i++) {
                drawStroke(mClip.strokes.get(i), drawCanvas, mPain);
            }
        }
    }

    public static void drawBackBitmap(Bitmap drawBitmap) {
        Canvas drawCanvas = new Canvas(drawBitmap);
        drawCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        PaintFlagsDrawFilter pfd = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        drawCanvas.setDrawFilter(pfd);
        //drawCanvas.drawColor(Color.BLACK);
        drawCanvas.drawARGB(153,0,0,0);
    }

//    public static void drawClipWithElement(Clip mClip, Bitmap drawBitmap, Paint mPain) {
//        drawClip(mClip, drawBitmap, mPain);
//        drawElement(mClip,drawBitmap);
//    }

    public static void drawElement(Clip mClip,Bitmap drawBitmap){
        Canvas drawCanvas = new Canvas(drawBitmap);
        drawCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        if (mClip.elements.size()>0){
            drawCanvas.translate(mClip.matrix.offsetX, mClip.matrix.offsetY);
            drawCanvas.scale(mClip.matrix.m11, mClip.matrix.m22);
            for (int i=0;i<mClip.elements.size();i++){
                ClipElement element=mClip.elements.get(i);
                drawCanvas.drawBitmap(element.elementData,element.locationX,element.locationY,new Paint());
            }
        }
    }

    public  static void addElementToClip(Clip mClip,ClipElement element){
        if(element.elementData.getWidth()>mClip.clipWidth||element.elementData.getHeight()>mClip.clipHeight){
            element.elementData=BitmapOperate.getBitmap(element.elementData,mClip.clipWidth,mClip.clipHeight);
        }
        if (element.elementData.getWidth()<mClip.clipWidth){
            element.locationX=(mClip.clipWidth-element.elementData.getWidth())/2;
        }

        if (element.elementData.getHeight()<mClip.clipHeight){
            element.locationY=(mClip.clipWidth-element.elementData.getHeight())/2;
        }
        mClip.elements.add(element);
    }


    //画点集
    public static void drawPoints(List<Point> mPoints, Clip ParentClip, Bitmap drawBitmap, Paint mPain, boolean isClose) {
        Canvas drawCanvas = new Canvas(drawBitmap);
        PaintFlagsDrawFilter pfd = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        drawCanvas.setDrawFilter(pfd);
        drawCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        drawCanvas.translate(ParentClip.matrix.offsetX, ParentClip.matrix.offsetY);
        drawCanvas.scale(ParentClip.matrix.m11, ParentClip.matrix.m22);
        drawPoints(mPoints,drawCanvas,mPain,isClose);
    }

    //清楚画布
    public static void clearBitmap(Bitmap drawBitmap) {
        Canvas drawCanvas = new Canvas(drawBitmap);
        drawCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    }

    //画矩形
    public static void drawRect(Bitmap drawBitmap, Rect mRect, Paint mPaint) {
        Canvas drawCanvas = new Canvas(drawBitmap);
        drawCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        drawCanvas.drawRect(mRect, mPaint);
    }

    //画笔画
    public static void drawStroke(Stroke mStroke, Canvas writeCanvas, Paint drawPaint) {
        drawPaint.setColor(mStroke.color);
        drawPaint.setStrokeWidth(mStroke.width);
        if (mStroke.points.size() > 1) {
            drawPoints(mStroke.points, writeCanvas, drawPaint, false);
        }
    }


    //画点集
    private static void drawPoints(List<Point> drawPoints, Canvas drawingBoard, Paint drawPaint, boolean isClose) {
        Path mPath = new Path();
        mPath.reset();
        if (drawPoints.size() > 1) {
            for (int i = 0; i < drawPoints.size(); i++) {
                if (i == 0) {
                    mPath.moveTo(drawPoints.get(i).X, drawPoints.get(i).Y);
                } else if (i < drawPoints.size() - 2) {
                    float x1 = (drawPoints.get(i).X + drawPoints.get(i + 1).X) / 2;
                    float y1 = (drawPoints.get(i).Y + drawPoints.get(i + 1).Y) / 2;
                    mPath.quadTo(drawPoints.get(i).X, drawPoints.get(i).Y, x1, y1);
                    //mPath.lineTo(drawPoints.get(i).X, drawPoints.get(i).Y);
                } else if (i == drawPoints.size() - 2) {
                    mPath.quadTo(drawPoints.get(i).X, drawPoints.get(i).Y, drawPoints.get(i + 1).X, drawPoints.get(i + 1).Y);
                    //mPath.lineTo(drawPoints.get(i).X, drawPoints.get(i).Y);
                }
            }
            if (isClose) {
                mPath.close();
            }
            drawingBoard.drawPath(mPath, drawPaint);
        }
    }

    //放大Clip
    public static void scaleClip(Clip mClip, float mScale) {
        if ((float) Math.round(mClip.matrix.m11 * 100) / 100 == 1f && mScale < 0) {
            mClip.matrix.m11 = 1;
            mClip.matrix.m22 = 1;
            return;
        } else if (mScale > 0 && (float) Math.round(mClip.matrix.m11 * 100) / 100 == 5f) {
            return;
        }
        mClip.matrix.m11 = Math.max(Math.min(mClip.matrix.m11 + mScale, 5f), 1f);
        mClip.matrix.m22 = Math.max(Math.min(mClip.matrix.m22 + mScale, 5f), 1f);

        reCalculateOffset(mClip);
        calculateOffset(mClip, mScale);
    }

    private static void calculateOffset(Clip mClip, float mScale) {
        if ((float) Math.round(mClip.matrix.m11 * 100) / 100 == 1f) {
            mClip.matrix.m11 = 1;
            mClip.matrix.m22 = 1;
            mClip.matrix.offsetX = 0;
            mClip.matrix.offsetY = 0;
            return;
        }
        mClip.matrix.offsetX = mClip.matrix.offsetX - mClip.clipWidth * mScale / 2;
        mClip.matrix.offsetY = mClip.matrix.offsetY - mClip.clipHeight * mScale / 2;
        minOffset(mClip);
    }

    private static void reCalculateOffset(Clip mClip) {
        if ((float) Math.round(mClip.matrix.m11 * 100) / 100 == 1f) {
            mClip.minOffsetY = mClip.minOffsetX = 0;
            return;
        }

        mClip.minOffsetX = 0 - (mClip.matrix.m11 - 1) * mClip.clipWidth;
        mClip.minOffsetY = 0 - (mClip.matrix.m11 - 1) * mClip.clipHeight;
    }

    public static void setOffset(Clip mClip, float offsetX, float offsetY) {
        mClip.matrix.offsetX = mClip.matrix.offsetX + offsetX;
        mClip.matrix.offsetY = mClip.matrix.offsetY + offsetY;
        minOffset(mClip);
    }

    private static void minOffset(Clip mClip) {
        mClip.matrix.offsetX = mClip.matrix.offsetX > mClip.minOffsetX ? mClip.matrix.offsetX : mClip.minOffsetX;
        mClip.matrix.offsetY = mClip.matrix.offsetY > mClip.minOffsetY ? mClip.matrix.offsetY : mClip.minOffsetY;
        mClip.matrix.offsetX = mClip.matrix.offsetX < 0 ? mClip.matrix.offsetX : 0;
        mClip.matrix.offsetY = mClip.matrix.offsetY < 0 ? mClip.matrix.offsetY : 0;
    }

    //赋值Clip
    public static void setClipData(Clip mClip, ClipData mClipData) {
        mClip.strokes = mClipData.strokes;
        mClip.id = mClipData.id;
        mClip.matrix = mClipData.matrix;
    }

    //新增还原状态
    public static void addUndo(Clip mClip) {
        mClip.redoClips.clear();
        mClip.redoIndex = -1;

        if (mClip.undoClip.size() == 0 || !mClip.undoClip.get(mClip.undoClip.size() - 1).equals(mClip.strokes)) {
            mClip.undoClip.add((List<Stroke>) CommonMethod.cloneObject(mClip.strokes));
            mClip.undoIndex = mClip.undoClip.size() - 1;
        }
    }

    //还原
    public static void undo(Clip mClip) {
        if (mClip.undoIndex > 0) {
            //mClip.undoIndex;
            mClip.redoClips.add((List<Stroke>) CommonMethod.cloneObject(mClip.strokes));
            mClip.redoIndex++;
            mClip.undoClip.remove(mClip.undoIndex);
            mClip.undoIndex--;
            mClip.strokes = (List<Stroke>) CommonMethod.cloneObject(mClip.undoClip.get(mClip.undoIndex));

        }
    }

    //撤销还原
    public static void redo(Clip mClip) {
        if (mClip.redoIndex > -1) {
            mClip.undoClip.add((List<Stroke>) CommonMethod.cloneObject(mClip.redoClips.get(mClip.redoIndex)));
            mClip.undoIndex++;
            mClip.strokes = (List<Stroke>) CommonMethod.cloneObject(mClip.redoClips.get(mClip.redoIndex));
            mClip.redoClips.remove(mClip.redoIndex);
            mClip.redoIndex--;
        }
    }

    //获取选中的笔画
    public static void getSelectStrokes(Clip mClip, Stroke strokeOut, List<Stroke> selectedStroke) {
        for (int i = 0; i < mClip.strokes.size(); i++) {
            if (isStrokeIn(mClip.strokes.get(i), strokeOut)) {
                selectedStroke.add(mClip.strokes.get(i));
            }
        }
    }

    //新增笔画
    public static void addStrokes(Clip mClip, List<Stroke> addStrokes) {
        mClip.strokes.addAll(addStrokes);
    }

    //移除笔画
    public static void removeStrokes(Clip mClip, List<Stroke> removeStrokes) {
        for (int i = mClip.strokes.size() - 1; i >= 0; i--) {
            for (int j = 0; j < removeStrokes.size(); j++) {
                if (removeStrokes.get(j).id.equals(mClip.strokes.get(i).id)) {
                    mClip.strokes.remove(i);
                    break;
                }
            }
        }
    }

    //判断strokeIn是否在strokeOut的范围，目前用得很简单矩形法
    private static boolean isStrokeIn(Stroke strokeIn, Stroke strokeOut) {
        if (strokeIn.GetMinX() < strokeOut.GetMinX() || strokeIn.GetMaxX() > strokeOut.GetMaxX() ||
                strokeIn.GetMaxY() > strokeOut.GetMaxY() || strokeIn.GetMinY() < strokeOut.GetMinY()) {
            return false;
        }
        return true;
    }


    //有限制的移动笔画组
    public static void moveStrokeWithLimit(List<Stroke> strokes, Point movePoint, Clip parentClip) {
        for (int i = 0; i < strokes.size(); i++) {

            movePoint.X = Math.min(parentClip.clipWidth - strokes.get(i).GetMaxX(), movePoint.X);
            movePoint.X = Math.max(0 - strokes.get(i).GetMinX(), movePoint.X);

            movePoint.Y = Math.min(parentClip.clipHeight - strokes.get(i).GetMaxY(), movePoint.Y);
            movePoint.Y = Math.max(0 - strokes.get(i).GetMinY(), movePoint.Y);

        }
        for (int i = 0; i < strokes.size(); i++) {
            for (int j = 0; j < strokes.get(i).points.size(); j++) {
                Point p = strokes.get(i).points.get(j);
                p.X = p.X + movePoint.X;
                p.Y = p.Y + movePoint.Y;
            }
        }
    }


    //无限制的移动笔画组
    public static void moveStrokeWithoutLimit(List<Stroke> strokes, Point movePoint) {
        for (int i = 0; i < strokes.size(); i++) {
            for (int j = 0; j < strokes.get(i).points.size(); j++) {
                Point p = strokes.get(i).points.get(j);
                p.X = p.X + movePoint.X;
                p.Y = p.Y + movePoint.Y;
            }
        }
    }


    //无限制的放大笔画
    public static void scaleStrokeWithoutLimit(List<Stroke> strokes, Clip parentClip, List<Stroke> orginalStrokes, float scale) {
        Stroke oStroke;
        float minX = 1000000;
        float maxX = 0;
        float minY = 1000000;
        float maxY = 0;
        for (int i = 0; i < orginalStrokes.size(); i++) {
            oStroke = orginalStrokes.get(i);
            maxX = Math.max(maxX, oStroke.GetMaxX());
            minX = Math.min(minX, oStroke.GetMinX());
            minY = Math.min(minY, oStroke.GetMinY());
            maxY = Math.max(maxY, oStroke.GetMaxY());
            for (int j = 0; j < strokes.size(); j++) {
                if (strokes.get(j).id.equals(oStroke.id)) {
                    scalePoint(strokes.get(j), oStroke, scale);
                }
            }
        }
        Point movePoint = new Point();
        movePoint.Y = 0 - (maxY - minY) / 2 * (scale - 1) - minY * (scale - 1);
        movePoint.X = 0 - (maxX - minX) / 2 * (scale - 1) - minX * (scale - 1);
        moveStrokeWithoutLimit(strokes, movePoint);
    }

    //有限制的放大笔画，限制为页面得高宽
    public static void scaleStrokeWithLimit(List<Stroke> strokes, Clip parentClip, List<Stroke> orginalStrokes, float scale) {
        Stroke oStroke;
        float minX = 1000000;
        float maxX = 0;
        float minY = 1000000;
        float maxY = 0;
        for (int i = 0; i < orginalStrokes.size(); i++) {
            oStroke = orginalStrokes.get(i);
            maxX = Math.max(maxX, oStroke.GetMaxX());
            minX = Math.min(minX, oStroke.GetMinX());
            minY = Math.min(minY, oStroke.GetMinY());
            maxY = Math.max(maxY, oStroke.GetMaxY());
            for (int j = 0; j < strokes.size(); j++) {
                if (strokes.get(j).id.equals(oStroke.id)) {
                    scalePoint(strokes.get(j), oStroke, scale);
                }
            }
        }
        Point movePoint = new Point();
        movePoint.Y = 0 - (maxY - minY) / 2 * (scale - 1) - minY * (scale - 1);
        movePoint.X = 0 - (maxX - minX) / 2 * (scale - 1) - minX * (scale - 1);
        moveStrokeWithLimit(strokes, movePoint, parentClip);

    }

    //将oStroke原始笔画放大为scale倍的新笔画nStroke
    private static void scalePoint(Stroke nStroke, Stroke oStroke, float scale) {
        for (int i = 0; i < oStroke.points.size(); i++) {
            nStroke.points.get(i).X = oStroke.points.get(i).X * scale;
            nStroke.points.get(i).Y = oStroke.points.get(i).Y * scale;
        }
    }

    //</editor-fold>

    //<editor-fold desc="相关计算">
    //根据Clip的缩放位移计算新点的位置
    public static void calculatePointByScale(Clip mClip, Point mPonit) {
        mPonit.Y = mPonit.Y - mClip.matrix.offsetY;
        mPonit.X = mPonit.X - mClip.matrix.offsetX;
        mPonit.Y = mPonit.Y / mClip.matrix.m22;
        mPonit.X = mPonit.X / mClip.matrix.m11;
    }


    //在一批点中找到对应的点
    public static Point searchPoint(List<Point> Points, int id) {
        for (int i = 0; i < Points.size(); i++) {
            if (Points.get(i).pointId == id) {
                return Points.get(i);
            }
        }
        return null;
    }

    //计算两个点之间的距离(是向量)
    public static float getAbsoluteValue(Point point1, Point point2) {
        int k = 1;
        if (point1.X - point2.X < 0) {
            k = -1;
        }
        return (float) Math.sqrt(Math.pow(point1.X - point2.X, 2) + Math.pow(point1.Y - point2.Y, 2)) * k;
    }

    //</editor-fold>
}
